import { EVENT_PICK_SHOW, EVENT_PICK_HIDE, EVENT_ARROW, EVENT_ASSET_RELOAD,
	EVENT_COMPLETE, EVENT_SEAT } from "../../compute/events";
import { color, layouts, paths, assets, createMask,
	fetchPickManifest, createPickImages } from "./layout";
import { ZRenderComp } from '../../../common/component/zrComp';
import { cubicOut, cubicInOut, cubicIn } from '../../../common/animation';
// import { SingleAnimationComp, cubicOut, cubicInOut, calc } from './baseComp';

const seatMap = {
	PL1 : 'top',
	PR1 : 'top',
	PL2 : 'jug',
	PR2 : 'jug',
	PL3 : 'mid',
	PR3 : 'mid',
	PL4 : 'bot',
	PR4 : 'bot',
	PL5 : 'sup',
	PR5 : 'sup',
};

const maskMap = {
	left : createMask(color.left),
	right : createMask(color.right),
};

let pickManifest;
/** @type {Promise} */
let pickManifestPromise;
let pickInited = false;

class PickSeat extends ZRenderComp {
	// const
	layout = {
		x: 0, ySrc: 242, yDst: 0, width: 158, height: 242,
		splitX: 157, splitY1: 14, splitY2: 230, splitWidth: 1,
		nameX: 9, nameY: 230, nameWidth: 140,
	};

	// value
	seatName = '';
	left = true;
	baseTime = 0; // 用于渐变 spGradient 的时间校准
	selectedTime = 0;

	constructor(args) {
		super(args.parent, args.zrender);

		this.left = args.left;
		this.seatName = args.seatName;
		Object.assign(this.layout, layouts.pickSeats[this.seatName]);
		this.useExistZRenderInstance(args.zr, this.layout.x, this.layout.ySrc);

		// events
		this.on(EVENT_PICK_SHOW, this.onPickEvent.bind(this, true));
		this.on(EVENT_PICK_HIDE, this.onPickEvent.bind(this, false));
		this.on(EVENT_ARROW, this.onArrow.bind(this));
		this.on(EVENT_SEAT, this.onSeat.bind(this));
		this.on(EVENT_COMPLETE, this.onSelected.bind(this));
		this.on(EVENT_ASSET_RELOAD, this.onAssetReload.bind(this));

		if (!pickInited) {
			pickInited = true;
			pickManifestPromise = fetchPickManifest(this.root.context)
					.then(d => { pickManifest = d });
		}
	}
	
	init() {
		const { layout, left } = this;

		this.spBg = this.createRect(layout.width, layout.height)
			.fillLinearGradient(0, 0, 0, 1, [
				{offset:0.05, color:color.pickSeats.bg1},
				{offset:0.95, color:color.pickSeats.bg2}
			])
			.z(0, 101)
			.build();
		this.spSplit = this.createRect(layout.splitWidth, layout.splitY2 - layout.splitY1)
			.fill(color.pickSeats.split)
			.position(layout.splitX, layout.splitY1)
			.z(0, 199)
			.build();

		// icon
		const seatType = seatMap[this.seatName];
		const lightPath = paths[seatType].light;
		const darkPath = paths[seatType].dark;

		// 左上角的图标
		this.spIcon = this.createPathFromString(lightPath)
			.fill(left ? color.left : color.right)
			.z(0, 120)
			.build();
		if (darkPath != null) {
			this.spIconDark = this.createPathFromString(darkPath)
				.fill(left ? color.left : color.right)
				.opacity(0.33)
				.z(0, 120)
				.build();
		}

		this.spName = this.createText(this.root.banPick.players[this.seatName], 24)
			.textFill(left ? color.left : color.right)
			.textStyle('left', 'bottom', 700, 'Arial')
			.position(layout.nameX, layout.nameY)
			.z(0, 193)
			.build();
		let scale = layout.nameWidth / this.spName.getBoundingRect().width;
		if (scale < 1) {
			this.spName.scaleTo(scale, 1);
		}

		this.spGradient = this.createRect(layout.width, layout.height)
			.fillLinearGradient(0, 0, 0, 1, [
				{offset:0.05, color:left ? color.leftTransparent : color.rightTransparent},
				{offset:0.95, color:left ? color.left : color.right}
			])
			.z(0, 192)
			.build();
		this.spGradient.hide();
		this.spMask = this.createImage(this.left ? maskMap.left : maskMap.right)
			.opacity(0)
			.z(0, 193)
			.build();
		this.spMask.hide();
	}

	tick(now) {
		super.tick(now);
		if (this.baseTime || this.selectedTime) {
			this.makeDirty();
		}
	}

	paint() {
		super.paint();

		if (this.baseTime) {
			const duration = (Date.now() - this.baseTime) % 2000;
			this.spGradient.attr({
				style: {opacity: cubicInOut(Math.abs((duration - 1000) / 1000))}
			});
		}
		if (this.selectedTime) {
			const duration = Date.now() - this.selectedTime;
			if (duration >= 800) {
				this.spMask.hide();
				this.selectedTime = 0;
			} else {
				this.spMask.attr({
					style: {opacity:　cubicInOut(1 - Math.abs(1 - duration / 400))}
				});
			}
		}
	}

	onPickEvent(show, _, event) {
		/** @type {string[]} */
		if (event.seats.indexOf(this.seatName) < 0) {
			return;
		}

		const { layout } = this;
		this.clearAnimations();
		this.getAnimY().update()
			.when(0, show ? layout.ySrc : layout.yDst)
			.when(400, show ? layout.yDst : layout.ySrc).easing(show ? cubicOut : cubicIn)
			.commit();
	}

	onArrow(_, param) {
		/** @type {string[]} */
		const seats = param.seats;
		if (!seats.find((seat) => seat === this.seatName)) {
			this.baseTime = 0;
			this.updateState();
			return;
		}

		if (this.baseTime) {
			return;
		}

		this.baseTime = Date.now();
		this.updateState();
		this.makeDirty();
	}

	onSeat(_, param) {
		/** @type {string} */ const seat = param.seat;
		if (this.seatName != seat) {
			return;
		}

		/** @type {string} */ const hero = param.hero;
		if (hero != '') {
			this.buildImage(hero);
		}
		this.updateState();
	}

	onSelected(_, param) {
		/** @type {string[]} */
		const seats = param.seats;
		if (!seats.find((seat) => seat === this.seatName)) {
			return;
		}
		this.selectedTime = this.selectedTime ? this.selectedTime : Date.now();
		this.spMask.show();
	}

	onAssetReload() {
		const bp = this.root.banPick;
		this.spName.attr({ style : {text : bp.players[this.seatName] }});
	}

	updateState() {
		const selecting = this.baseTime != 0;
		const selected = this.root.banPick.seatSelect[this.seatName] != '';
		// 正在选, spGradient show; 不在选, spGradient hide;
		selecting ? this.spGradient.show() : this.spGradient.hide();

		// 图标和名字
		// hero 存在或正在选, spIcon hide, spName 白色; 否则 spIcon show, spName 主题色
		if (selected || selecting) {
			this.spIcon.hide();
			this.spIconDark && this.spIconDark.hide();
			this.spName.attr({ style : { textFill: color.white } });
		} else {
			this.spIcon.show();
			this.spIconDark && this.spIconDark.show();
			this.spName.attr({ style : { textFill: this.left ? color.left : color.right } });
		}

		if (!selected && this.spImage) {
			this.removeImage();
		}
	}

	removeImage() {
		this.spImage && this.spImage.destroy();
	}

	buildImage(hero) {
		const { layout } = this;

		new Promise((resolve, reject) => {
			if (pickManifest) {
				resolve(pickManifest);
			}
			pickManifestPromise
					.then(_ => resolve(pickManifest))
					.catch(_ => reject(hero));
		}).then(manifest => {
			return createPickImages(manifest, hero, this.root.context.assetPath(assets.pickPathFunc(hero)))
		}).then(canvas => {
			this.removeImage();
			this.spImage = this.createImage(canvas, layout.width, layout.height)
				.z(0, 110)
				.build();
		});
	}
}

export {
	PickSeat
};